﻿using Castle.Core.Internal;
using MySql.Data.MySqlClient;
using Ongoal.Quotation.Service.Param;
using System.Data;
using System.Diagnostics;
using System.Reflection;
using System.Text;

namespace Ongoal.Quotation.Service.Common
{
    /// <summary>
    /// 数据帮助类
    /// </summary>
    public class DataHelper
    {
        /// <summary>
        /// 比较--两个类型一样的实体类对象的值
        /// </summary>
        /// <param name="oneT"></param>
        /// <returns>返回true表示两个对象的数据相同，返回false表示不相同</returns>
        public static bool CompareType<T>(T oneT, T twoT)
        {
            bool result = true;//两个类型作比较时使用,如果有不一样的就false
            Type typeOne = oneT.GetType();
            Type typeTwo = twoT.GetType();
            //如果两个T类型不一样  就不作比较
            if (!typeOne.Equals(typeTwo)) { return false; }
            PropertyInfo[] pisOne = typeOne.GetProperties(); //获取所有公共属性(Public)
            PropertyInfo[] pisTwo = typeTwo.GetProperties();
            //如果长度为0返回false
            if (pisOne.Length <= 0 || pisTwo.Length <= 0)
            {
                return false;
            }
            //如果长度不一样，返回false
            if (!(pisOne.Length.Equals(pisTwo.Length))) { return false; }
            //遍历两个T类型，遍历属性，并作比较
            for (int i = 0; i < pisOne.Length; i++)
            {
                //获取属性名
                string oneName = pisOne[i].Name;
                string twoName = pisTwo[i].Name;
                //获取属性的值
                object oneValue = pisOne[i].GetValue(oneT, null);
                object twoValue = pisTwo[i].GetValue(twoT, null);
                //比较,只比较值类型
                if ((pisOne[i].PropertyType.IsValueType || pisOne[i].PropertyType.Name.StartsWith("String")) && (pisTwo[i].PropertyType.IsValueType || pisTwo[i].PropertyType.Name.StartsWith("String")))
                {
                    if (oneName.Equals(twoName))
                    {
                        if (oneValue == null)
                        {
                            if (twoValue != null)
                            {
                                result = false;
                                break; //如果有不一样的就退出循环
                            }
                        }
                        else if (oneValue != null)
                        {
                            if (twoValue != null)
                            {
                                if (!oneValue.Equals(twoValue))
                                {
                                    result = false;
                                    break; //如果有不一样的就退出循环
                                }
                            }
                            else if (twoValue == null)
                            {
                                result = false;
                                break; //如果有不一样的就退出循环
                            }
                        }
                    }
                    else
                    {
                        result = false;
                        break;
                    }
                }
                else
                {
                    //如果对象中的属性是实体类对象，递归遍历比较
                    bool b = CompareType(oneValue, twoValue);
                    if (!b) { result = b; break; }
                }
            }
            return result;
        }


        /// <summary>
        /// DataTable分页
        /// </summary>
        /// <param name="dt">DataTable数据</param>
        /// <param name="PageIndex">第几页</param>
        /// <param name="PageSize">每页的记录数</param>
        /// <returns></returns>
        public static DataTable GetPagedTable(DataTable dt, int PageIndex, int PageSize, string Sort = "CreateTime", string Desc = "desc")//PageIndex表示第几页，PageSize表示每页的记录数
        {
            if (PageIndex == 0)
                return dt;//0页代表每页数据，直接返回

            DataTable newdt = dt.Copy();
            newdt.Clear();//copy dt的框架

            int rowbegin = (PageIndex - 1) * PageSize;
            int rowend = PageIndex * PageSize;

            if (rowbegin >= dt.Rows.Count)
                return newdt;//源数据记录数小于等于要显示的记录，直接返回dt

            if (rowend > dt.Rows.Count)
                rowend = dt.Rows.Count;
            for (int i = rowbegin; i <= rowend - 1; i++)
            {
                DataRow newdr = newdt.NewRow();
                DataRow dr = dt.Rows[i];
                foreach (DataColumn column in dt.Columns)
                {
                    newdr[column.ColumnName] = dr[column.ColumnName];
                }
                newdt.Rows.Add(newdr);
            }
            newdt.DefaultView.Sort = Sort + " " + Desc;
            return newdt;
        }
        /// <summary>
        /// 将文件转换为 Stream
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static Stream FileToStream(string fileName)
        {

            // 打开文件

            FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);

            // 读取文件的 byte[]

            byte[] bytes = new byte[fileStream.Length];

            fileStream.Read(bytes, 0, bytes.Length);

            fileStream.Close();

            // 把 byte[] 转换成 Stream

            Stream stream = new MemoryStream(bytes);

            return stream;

        }

        /// <summary>
        /// MySql数据库备份sd
        /// </summary>
        /// <param name="Param">请求参数</param>
        public static async Task<dynamic> MySqlBackUp(PublicParam Param)
        {
            try
            {
                using (MySqlCommand cmd = new MySqlCommand())
                {
                    MySqlConnection conn = new MySqlConnection(Param.ConStr);
                    string Time = DateTime.Now.ToString("yyyyMMddHHmmss");
                    string[] connArray = Param.ConStr.Split(';');
                    string FileName = Time;
                    foreach (var str in connArray)
                    {
                        if (str.ToLower().Contains("database"))
                        {
                            FileName += str.Substring(str.IndexOf('=') + 1);
                            break;
                        }
                    }
                    FileName += ".sql";
                    //获取数据库名
                    string file = Param.FileStr + FileName;
                    using (MySqlBackup mb = new MySqlBackup(cmd))
                    {

                        cmd.Connection = conn;

                        conn.Open();

                        mb.ExportToFile(file);

                        conn.Close();

                        MongoFileRepo mongoFile = new MongoFileRepo();
                        var result = await mongoFile.UploadFile(FileName, FileToStream(file), "");

                        return "备份与文件上传成功";
                    }
                }
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// MongoDB数据库备份
        /// </summary>
        /// <param name="Param">请求参数</param>
        public static void MongoDBBackUp(PublicParam Param)
        {
            string Time = DateTime.Now.ToString("yyyyMMddHHmmss");
            string[] connArray = Param.ConStr.Split(';');
            string FileName = Time;
            StringBuilder sb = new StringBuilder();
            sb.Append("mongodump ");
            foreach (var str in connArray)
            {
                var value = str.Substring(str.IndexOf('=') + 1);
                if (str.ToLower().Contains("server"))
                {
                    sb.AppendFormat(" -h {0}", value);
                }
                if (str.ToLower().Contains("port"))
                {
                    sb.AppendFormat(" -port {0}", value);
                }
                if (str.ToLower().Contains("user"))
                {
                    sb.AppendFormat(" -u {0}", value);
                }
                if (str.ToLower().Contains("password"))
                {
                    sb.AppendFormat(" -p {0}", value);
                }
                if (str.ToLower().Contains("database"))
                {
                    sb.AppendFormat(" -d {0}", value);
                    FileName += value;
                }
            }
            sb.AppendFormat(" -o {0}", Param.FileStr + FileName);
            ExeCommand(sb.ToString());
        }

        /// <summary>
        /// 执行cmd命令
        /// </summary>
        /// <param name="commandText"></param>
        /// <returns></returns>
        public static string ExeCommand(string commandText)
        {
            Process p = new Process();
            p.StartInfo.FileName = "cmd.exe";
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardInput = true;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.RedirectStandardError = true;
            p.StartInfo.CreateNoWindow = true;
            string strOutput = null;
            try
            {
                p.Start();
                p.StandardInput.WriteLine(commandText);
                p.StandardInput.WriteLine("exit");
                strOutput = p.StandardOutput.ReadToEnd();
                p.WaitForExit();
                p.Close();
            }
            catch (Exception e)
            {
                strOutput = e.Message;
            }
            return strOutput;
        }

        /// <summary>
        /// 两个实体之间相同属性的映射
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static R Mapping<R, T>(T model)
        {
            R result = Activator.CreateInstance<R>();
            var type = model!.GetType();
            foreach (PropertyInfo info in typeof(R).GetProperties())
            {
                PropertyInfo pro = type.GetProperty(info.Name)!;
                if (pro != null)
                {
                    var Value = pro.GetValue(model);
                    if (Value != null)
                    {
                        if (info.PropertyType.Name.StartsWith("Nullable"))
                            info.SetValue(result, Convert.ChangeType(Value, info.PropertyType.GenericTypeArguments[0]));
                        else
                            info.SetValue(result, Convert.ChangeType(Value, info.PropertyType));
                    }
                    else
                        info.SetValue(result, null);
                }

            }
            return result;
        }

        /// <summary>
        /// 两个实体之间相同属性的映射
        /// </summary>
        /// <typeparam name="R"></typeparam>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static R Mapping<R>(object model)
        {
            R result = Activator.CreateInstance<R>();
            var type = model.GetType();
            var props = typeof(R).GetProperties();
            foreach (PropertyInfo info in props)
            {
                var pro = type.GetProperty(info.Name);
                if (pro != null)
                {
                    var Value = pro.GetValue(model);
                    if (Value != null)
                    {
                        try
                        {
                            var value = Convert.ChangeType(Value, info.PropertyType);
                            info.SetValue(result, value);
                        }
                        catch (Exception)
                        {
                            continue;
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 标识+年月日+流水号
        /// </summary>
        /// <param name="SN">标识</param>
        /// <param name="Serial">原流水号</param>
        /// <param name="Number">几位流水号</param>
        /// <returns></returns>
        public static string SerialNumber(string SN, string Serial, string Number = "000001")
        {
            var dateStr = SN + DateTime.Now.ToString("yyyyMMdd");
            var serialNumberStr = Number;
            if (!Serial.IsNullOrEmpty())
            {
                var serialNumber = Serial.Substring(Serial.Length - Number.Length);
                var Num = int.Parse(serialNumber) + 1;
                serialNumberStr = Num.ToString().PadLeft(Number.Length, '0');
            }
            return dateStr + serialNumberStr;
        }
    }
}
